#pragma once

#include "pch.h"
#include "CubeRenderer.h"
#include <DrawingSurfaceNative.h>

namespace PhoneXamlDirect3DApp1Comp
{

public delegate void RequestAdditionalFrameHandler();
public delegate void RecreateSynchronizedTextureHandler();
public delegate void RendererInitializedHandler();
public delegate void OnRenderHandler();

[Windows::Foundation::Metadata::WebHostHidden]
public ref class Direct3DInterop sealed : public Windows::Phone::Input::Interop::IDrawingSurfaceManipulationHandler
{
public:
	Direct3DInterop();

	Windows::Phone::Graphics::Interop::IDrawingSurfaceContentProvider^ CreateContentProvider();

	// IDrawingSurfaceManipulationHandler
	virtual void SetManipulationHost(Windows::Phone::Input::Interop::DrawingSurfaceManipulationHost^ manipulationHost);

	event RequestAdditionalFrameHandler^ RequestAdditionalFrame;
	event RecreateSynchronizedTextureHandler^ RecreateSynchronizedTexture;
	event RendererInitializedHandler^ RendererInitialized;
	event RendererInitializedHandler^ RendererUnitialized;

	event OnRenderHandler^ OnRender;

	property Windows::Foundation::Size WindowBounds;
	property Windows::Foundation::Size NativeResolution;
	property Windows::Foundation::Size RenderResolution
	{
		Windows::Foundation::Size get(){ return m_renderResolution; }
		void set(Windows::Foundation::Size renderResolution);
	}

	void RegisterTexture(Texture^ texture)
	{
		if (m_renderer != nullptr)
		{
			m_renderer->RegisterTexture(texture);
		}
	}
	void UnregisterTexture(Texture^ texture)
	{
		if (m_renderer != nullptr)
		{
			m_renderer->UnregisterTexture(texture);
		}
	}
	void UpdateTexture(Texture^ texture)
	{
		if (m_renderer != nullptr)
		{
			m_renderer->UpdateTexture(texture);
		}
	}
	void BeginRender()
	{
		if (m_renderer != nullptr)
		{
			m_renderer->BeginRender();
		}
	}

	bool IsRendererInitialized()
	{
		return m_renderer != nullptr;
	}

	void Draw(Vector4 rectangle, Color color)
	{
		if (m_renderer != nullptr)
		{
			m_renderer->Draw(rectangle, color);
		}
	}
	void Draw(Vector4 rectangle, Color color, Texture^ texture, Vector4 destinationTextureUV)
	{
		if (m_renderer != nullptr)
		{
			if (texture == nullptr)
			{
				m_renderer->Draw(rectangle, color);
			}
			else
			{
				m_renderer->Draw(rectangle, color, texture, destinationTextureUV);
			}
		}
	}
	void DrawLine(Vector2 start, Vector2 end, Color color)
	{
		if (m_renderer != nullptr)
		{
			m_renderer->DrawLine(start, end, color);
		}
	}
	void DrawCircle(Vector2 position, double radius, Color color)
	{
		if (m_renderer != nullptr)
		{
			m_renderer->DrawCircle(position, radius, color);
		}
	}
	void DrawTriangles(long long vertices, int verticesLength, unsigned short* indices, int indicesLength, long long colors, int colorLength)
	{
		if (m_renderer != nullptr)
		{
			// Convert to native.
			Vector2* verticesNative = reinterpret_cast<Vector2*>(vertices);
			ColorNative* colorsNative = reinterpret_cast<ColorNative*>(colors);

			m_renderer->DrawTriangles(verticesNative, verticesLength, indices, indicesLength, colorsNative, colorLength);
		}
	}
	void EndRender()
	{
		if (m_renderer != nullptr)
		{
			m_renderer->EndRender();
		}
	}

internal:
	HRESULT STDMETHODCALLTYPE Connect(_In_ IDrawingSurfaceRuntimeHostNative* host);
	void STDMETHODCALLTYPE Disconnect();
	HRESULT STDMETHODCALLTYPE PrepareResources(_In_ const LARGE_INTEGER* presentTargetTime, _Out_ BOOL* contentDirty);
	HRESULT STDMETHODCALLTYPE GetTexture(_In_ const DrawingSurfaceSizeF* size, _Inout_ IDrawingSurfaceSynchronizedTextureNative** synchronizedTexture, _Inout_ DrawingSurfaceRectF* textureSubRectangle);
	ID3D11Texture2D* GetTexture();

private:
	CubeRenderer^ m_renderer;
	Windows::Foundation::Size m_renderResolution;
};

}
